﻿using System;
using System.Text;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Media;
using Microsoft.Phone.Tasks;
using TheVerge.Base;
using TheVerge.Phone.Converters;
using TheVerge.Phone.Imp;
using Microsoft.Phone.Controls;
using TheVerge.Base.Models;
using Microsoft.Phone.Shell;
using System.Collections.Generic;
using System.Windows.Media.Animation;

namespace TheVerge.Phone.Controls
{
    /// <summary>
    /// Special thanks to the following for help with launching all links in
    /// a web browser task instead of the existing WebBrowserControl.
    /// See: http://4mkmobile.com/2010/10/quick-tip-changing-all-links-to-open-using-the-webbrowsertask/
    /// </summary>
    public partial class ArticleEntryControl : UserControl
    {
        //-- Original Font Size
        // Body: 128%
        // Title: 176%
        // Diff: 1.375
        #region HTML
        /// <summary>
        /// http://social.msdn.microsoft.com/forums/en-us/wpdevelop/thread/3c5107dc-f286-4d5d-98dd-0c688bd4f5e0
        /// Special thanks to that forum post to help see the value of including the doctype in the web browser control.
        /// </summary>
        private const string HTML = @"
<?xml version=""1.0"" encoding=""UTF-8""?>
<!DOCTYPE html PUBLIC ""-//WAPFORUM//DTD XHTML Mobile 1.2//EN"" ""http://www.openmobilealliance.org/tech/DTD/xhtml-mobile12.dtd"">
<html>
	<head>
		<meta name=""viewport"" content=""width={7}"" />
		<style type=""text/css"">
			body {{
				background-color:{0};
				color:{1};
				font-size:{5}%;
			}}
			a {{ color:{2}; }}

            img {{ max-width:99%; }}

			.Title {{
				font-size:{6}%;
				color:{2};
			}}

			.Subtle {{
				color:{3};
			}}

			.SourceName {{
				background-color:{2};
				border:2px solid {0};
				color:{0};
				padding:3px 5px;
				float: left;
			}}

			.SourceLinkDiv {{
				background-color:{3};
				border:2px solid {0};
				padding:3px 5px;
				float: left;
			}}

			.SourceLink {{ 
				text-decoration:none;
				color:{0};
			}}

		</style>
	</head>

	<body>{4}</body>
	<script>
			window.onload = function() {{
				a = document.getElementsByTagName('a');
				for(var i=0; i < a.length; i++) {{
					a[i].attachEvent('onclick', notify);
					
				}}
			}}

			function notify(evt) {{
				window.external.Notify(evt.srcElement.href); 

				if (evt) {{
					evt.returnValue = false;
				}} 
				
				return false;
			}}
		</script>	
</html>";
        #endregion

        private ArticleEntry ActiveArticle;
        private CompositeTransform moveTransform;
        
        private FromNowDateTimeConverter Conv = new FromNowDateTimeConverter();
        private Storyboard showSB;
        private Storyboard hideSB;
        private Duration sbDuration = new Duration(TimeSpan.FromSeconds(0.25D));

        public bool IsOverlayVisible { get { return commentsControl.IsVisible() || sharePane.IsVisible(); } }
        public bool IsVisible { get; private set; }

        public event EventHandler ArticleLoaded = delegate { };

        public ArticleEntryControl()
        {
            InitializeComponent();
            AppBarHelper.CommentsAction = ToggleComments;
            AppBarHelper.ShareAction = ToggleShare;

            this.RenderTransform = moveTransform = new CompositeTransform();

            //-- By Default it's hidden
            Opacity = 0D;
            moveTransform.TranslateY = ActualHeight;
        }

        public void InitArticleViewer(double width, double height)
        {
            Width = width;
            Height = height;

            //-- Hide
            CreateStoryBoard(ref hideSB, 0, height, 0D);

            //-- Show
            CreateStoryBoard(ref showSB, height * 0.2D, 0D, 1D);

            if (!IsVisible)
                moveTransform.TranslateY = height;
        }

        private void CreateStoryBoard(ref Storyboard sb, double fromY, double toY, double Opacity)
        {
            var translateY = new DoubleAnimation() { To = toY, From = fromY };
            var opacity = new DoubleAnimation() { To = Opacity };
            translateY.Duration = opacity.Duration = sbDuration;
            sb = new Storyboard();
            sb.Children.Add(translateY);
            sb.Children.Add(opacity);
            Storyboard.SetTarget(translateY, moveTransform);
            Storyboard.SetTarget(opacity, this);
            Storyboard.SetTargetProperty(translateY, new PropertyPath(CompositeTransform.TranslateYProperty));
            Storyboard.SetTargetProperty(opacity, new PropertyPath(FrameworkElement.OpacityProperty));
        }

        private IEnumerable<IApplicationBarIconButton> ArticleButtons
        {
            get
            {
                yield return AppBarHelper.IEButton;
                yield return AppBarHelper.ShareButton;
                yield return AppBarHelper.CommentsButton;
            }
        }

        private IEnumerable<IApplicationBarMenuItem> AppBarItems
        {
            get
            {
                yield return AppBarHelper.SettingsItem;
                yield return AppBarHelper.LoginItem;
            }
        }

        private IEnumerable<IApplicationBarIconButton> CommentButtons
        {
            get
            {
                yield return AppBarHelper.AddCommentButton;
                yield return AppBarHelper.ShareButton;
                yield return AppBarHelper.CommentsButton;
            }
        }

        public void HideOverlay()
        {
            if (sharePane.IsVisible())
                sharePane.Hide();
            else if (commentsControl.IsVisible())
            {
                if (!commentsControl.IsAddCommentDialogVisible)
                {
                    commentsControl.Hide();
                    AppBarHelper.Load(ArticleButtons, AppBarItems, false);
                }
            }
        }

        public void Hide()
        {
            AppBarHelper.LoadFromPage();
            IsVisible = false;
            hideSB.Begin();
        }

        public void LoadEntry(ArticleEntry e)
        {
            ActiveArticle = App.MainVM.ActiveArticle = e;
            AppBarHelper.Load(ArticleButtons, AppBarItems, false);

            HideOverlay();
            RefreshArticle();
            commentsControl.Load(e);
            IsVisible = true;
            showSB.Begin();
        }

        public void Refresh()
        {
            if (ActiveArticle != null)
                LoadEntry(ActiveArticle);
        }

        public void RefreshArticle()
        {
            if (null != ActiveArticle)
                theBrowser.NavigateToString(CreateHtml(ActiveArticle));
        }

        private string CreateHtml(ArticleEntry e)
        {
            var sb = new StringBuilder();
            sb.AppendFormat("<p class='Title'>{0}</p>", e.Title);
            if (e.HasPhoto)
                sb.AppendFormat("<img src='{0}' alt='Image' style='width:99%' />", e.LargeImageUri);
            sb.AppendFormat("<p>By <bold>{0}</bold> <span class='Subtle'>{1}</span></p>", e.AuthorName, Conv.Convert(e.PublishedOn, null, null, null));
            sb.Append(e.Body.Replace(@"src=""//", @"src=""http://"));
            sb.Append(GetSourceList("VIA", e.ViaList));
            sb.Append(GetSourceList("SOURCE", e.SourceList));
            sb.Append(@"<br />");
            sb.Append(@"<br />");

            var bodySize = Theme.Active.FontSize;
            var titleSize = bodySize * 1.375;

            return string.Format(HTML, GetHex(BackColor), GetHex(ForegroundColor), GetHex(AccentColor), GetHex(SubtleColor), sb, bodySize, titleSize, Width);
        }

        private static string GetSourceList(string sourceName, Source[] list)
        {
            if (null == list || list.Length == 0) return string.Empty;
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat(@"<div class='SourceName'>{0}</div>", sourceName);
            foreach (var s in list)
            {
                sb.AppendFormat(@"<div class='SourceLinkDiv'><a class='SourceLink' href='{0}'>{1}</a></div>", s.Url, s.Name.ToUpper());
            }
            sb.Append("<div style='clear:both;height:1px;' />");
            return sb.ToString();
        }

        private Color AccentColor { get { return ThemeManager.Accent; } }
        private Color BackColor { get { return ThemeManager.Background; } }
        private Color ForegroundColor { get { return ThemeManager.Foreground; } }
        private Color SubtleColor { get { return ThemeManager.Subtle; } }

        private static string GetHex(Color c)
        {
            return string.Format("#{0:X2}{1:X2}{2:X2}", c.R, c.G, c.B);
        }

        private void theBrowser_LoadCompleted(object sender, System.Windows.Navigation.NavigationEventArgs e)
        {
            ArticleLoaded(this, EventArgs.Empty);
        }

        private void theBrowser_NavigationFailed(object sender, System.Windows.Navigation.NavigationFailedEventArgs e)
        {
            ArticleLoaded(this, EventArgs.Empty);
            MessageBox.Show("There was an error loading the page.");
        }

        private void theBrowser_ScriptNotify(object sender, Microsoft.Phone.Controls.NotifyEventArgs e)
        {
            try
            {
                var wbt = new WebBrowserTask();
                wbt.Uri = new Uri(e.Value, UriKind.Absolute);
                wbt.Show();
            } //-- Sometimes we may get an invalid Uri, as a result, we need to catch this exception.
            catch (Exception)
            {
                MessageBox.Show("Unable to launch link. This could be do to a poorly formatted Uri or an invalid protocol.");
            }
        }

        private void ToggleComments()
        {
            if (commentsControl.IsVisible())
            {
                commentsControl.Hide();
                AppBarHelper.Load(ArticleButtons, AppBarItems, false);
            }
            else
            {
                commentsControl.Show();
                AppBarHelper.Load(CommentButtons, AppBarItems, false);
            }

            if (sharePane.IsVisible())
                sharePane.Hide();
        }

        #region Sharing
        #region Event Handlers
        private void Copy_Click(object sender, RoutedEventArgs e) { ArticleExecutor(Copy); }

        private void Email_Click(object sender, RoutedEventArgs e) { ArticleExecutor(Email); }

        private void SMS_Click(object sender, RoutedEventArgs e) { ArticleExecutor(SMS); }

        private void Social_Click(object sender, RoutedEventArgs e) { ArticleExecutor(Social); }
        #endregion

        private void ArticleExecutor(Action<ArticleEntry> action)
        {
            sharePane.Hide();

            var article = App.MainVM.ActiveArticle;
            if (article != null)
                action(article);
        }

        private void ToggleShare()
        {
            if (sharePane.IsVisible())
                sharePane.Hide();
            else
                sharePane.Show();
        }

        private void Copy(ArticleEntry article)
        {
            if (article == null) return;
            Clipboard.SetText(article.Url);
            MessageBox.Show(string.Format("'{0}' has been copied to your clipboard.", article.Url), "Link Copied", MessageBoxButton.OK);
        }

        private void Email(ArticleEntry article)
        {
            if (article == null) return;
            var t = new EmailComposeTask();
            t.Subject = article.Title;
            t.Body = string.Format("'{0}'\n\n via The Verge Windows Phone App", article.Url);
            t.Show();
        }

        private void SMS(ArticleEntry article)
        {
            if (article == null) return;
            var sms = new SmsComposeTask();
            sms.Body = string.Format("'{0}'\n\n{1}", article.Title, article.Url);
            sms.Show();
        }

        private void Social(ArticleEntry article)
        {
            if (article == null) return;

            var share = new ShareLinkTask();
            share.LinkUri = new Uri(article.Url);
            share.Title = article.Title;
            share.Show();
        }
        #endregion
    }
}
